package org.zhangkun.jmsg.webserver.server;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.zhangkun.jmsg.webserver.bean.Cookie;

/**
 * 
 * 
 * Copyright (C), 2006-2010, ChengDu Lovo info. Co., Ltd. FileName:
 * Response.java ������Ӧ��
 * 
 * @author zhangkun
 * @Date 2011-6-17
 * @version 1.00
 */
public class Response {

	public final static String HTTP_VERSION = "HTTP/1.1";
	/**
	 * ��Ӧ״̬��200 ��
	 */
	public final static int RESPONSE_CODE_200 = 200;
	public final static String RESPONSE_CODETEXT_200 = "OK";

	/**
	 * ��Ӧ״̬��404 ҳ��δ�ҵ�
	 */
	public final static int RESPONSE_CODE_404 = 404;
	public final static String RESPONSE_CODETEXT_404 = "Not Found";

	/**
	 * ��Ӧ״̬��500 �������쳣
	 */
	public final static int RESPONSE_CODE_500 = 500;
	public final static String RESPONSE_CODETEXT_500 = "Internal Server Error";

	/**
	 * ��Ӧ״̬��403 �޷�����
	 */
	public final static int RESPONSE_CODE_403 = 403;
	public final static String RESPONSE_CODETEXT_403 = "Forbidden";

	// ��ݿ�
	private ByteArrayOutputStream data = new ByteArrayOutputStream();

	// ��ݱ����ʽ��Ĭ��utf-8
	private String encoding = "utf-8";

	// ��Ӧͷ
	private HashMap<String, String> header;

	// Cookies
	private ArrayList<Cookie> allCookie = new ArrayList<Cookie>();

	// ��Ӧ����
	private int responseCode = RESPONSE_CODE_200;

	// ��Ӧ״̬
	private String responseCodeText = RESPONSE_CODETEXT_200;

	private OutputStream os;

	private boolean buffer = true;

	public Response(OutputStream os) {
		this.os = os;
		header = new HashMap<String, String>();
		setContentType("text/html");
	}

	public void addHeader(String name, String value) {
		// TODO Auto-generated method stub
		header.put(name, value);
	}

	public void clearAll() {
		// TODO Auto-generated method stub
		clearData();
		clearHeader();
	}

	public void clearData() {
		data.reset();
	}

	public void clearHeader() {
		header.clear();
	}

	/**
	 * ���һ��Cookie
	 * 
	 * @param c
	 */
	public void addCookie(Cookie c) {
		allCookie.add(c);
	}

	/**
	 * �Ƴ�һ��Cookie
	 * 
	 * @param c
	 */
	public void removeCookie(Cookie c) {
		allCookie.remove(c);
	}

	public byte[] getContents() {
		ByteArrayOutputStream allData = new ByteArrayOutputStream();
		setContentLength(data.size());
		header.put("Connection", "close");
		header.put("Server", "java web server");
		writeHeader(allData);
		try {
			allData.write(data.toByteArray());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return allData.toByteArray();
	}

	public ByteArrayOutputStream getData() {
		return data;
	}

	public String getEncoding() {
		return encoding;
	}

	public HashMap<String, String> getHeader() {
		return header;
	}

	public int getResponseCode() {
		return responseCode;
	}

	public void setContentLength(long l) {
		// TODO Auto-generated method stub
		header.put("Content-Length", l + "");
	}

	public void setContentType(String type) {
		header.put("Content-type", type);
	}

	public void setData(ByteArrayOutputStream data) {
		this.data = data;
	}

	/**
	 * ������ݵı��뷽ʽ
	 * 
	 * @param encoding
	 * @throws UnsupportedEncodingException
	 *             ����ı���
	 */
	public void setEncoding(String encoding)
			throws UnsupportedEncodingException {
		"".getBytes(encoding);
		this.encoding = encoding;
	}

	public void setResponseCode(int responseCode, String responseCodeText) {
		this.responseCode = responseCode;
		this.responseCodeText = responseCodeText;
	}

	/**
	 * д����ݵ�����
	 * 
	 * @param str
	 */
	public void write(byte[] bs) {
		try {
			data.write(bs);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * д����ݵ�����
	 * 
	 * @param str
	 */
	public void write(String str) {
		try {
			write(str.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
		}
	}

	/**
	 * ���ͷ��Ϣ
	 */
	private void writeHeader(OutputStream data) {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		sb.append(HTTP_VERSION + " " + responseCode + " " + responseCodeText
				+ "\r\n");
		Iterator<String> keys = header.keySet().iterator();
		while (keys.hasNext()) {
			String key = keys.next();
			sb.append(key + ": " + header.get(key) + "\r\n");
		}
		for (Cookie cookie : allCookie) {
			sb.append("Set-Cookie: " + cookie + "\r\n");
		}
		sb.append("\r\n");
		try {
			data.write(sb.toString().getBytes());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private boolean writeHeader = false;

	public void write(byte[] buffer, int i, int length) throws IOException {
		// TODO Auto-generated method stub
		if (!this.buffer) {
			if (!writeHeader) {
				writeHeader = true;
				writeHeader(os);
			}
			os.write(buffer, 0, length);
			os.flush();
		} else
			data.write(buffer, i, length);
	}

	public OutputStream getOs() {
		return os;
	}

	public void setBuffer(boolean buffer) {
		this.buffer = buffer;
	}

	public boolean isBuffer() {
		return buffer;
	}
}
